package com.netty.server.handler;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.reflect.FastClass;
import org.springframework.cglib.reflect.FastMethod;

import com.netty.common.protocol.RpcRequest;
import com.netty.common.protocol.RpcResponse;

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;

public class Task implements Runnable{
	private static final Logger logger = LoggerFactory.getLogger(Task.class);
	private ChannelHandlerContext ctx;
	private RpcRequest request;
	Map<String, Object> handlerMap;
	public Task(ChannelHandlerContext ctx, RpcRequest request, Map<String, Object> handlerMap){
		this.ctx = ctx;
		this.request = request;
		this.handlerMap = handlerMap;
	}

	@Override
	public void run() {
		logger.debug("Receive request "+request.getRequestId());
		RpcResponse response = new RpcResponse();
		response.setRequestId(request.getRequestId());
		try {
			Object result = handle(request);
			response.setResult(result);
		} catch (Throwable t) {
			response.setError(toString().toString());
			logger.error("RPC Server handle request error",t);
		}
		ctx.writeAndFlush(response).addListener(new ChannelFutureListener() {
			@Override
			public void operationComplete(ChannelFuture future) throws Exception {
				logger.debug("Send response for request " + request.getRequestId());
			}
		});
		
	}

	/**
	 * 处理请求
	 * @param request
	 * @return
	 * @throws Throwable
	 */
	private Object handle(RpcRequest request) throws Throwable {
		String className = request.getClassName();
		Object serviceBean = handlerMap.get(className);
		Class<?> serviceClass = serviceBean.getClass();
		String methodName = request.getMethodName();
		Class<?>[] parameterTypes = request.getParameterTypes();
		Object[] parameters = request.getParameters();
		logger.debug(serviceClass.getName());
		logger.debug(methodName);
		for (int i = 0; i < parameterTypes.length; i++) {
			logger.debug(parameterTypes[i].getName());
		}
		for (int i = 0; i < parameters.length; i++) {
			logger.debug(parameters[i].toString());
		}
		FastClass serviceFastClass = FastClass.create(serviceClass);
		FastMethod serviceFastMethod = serviceFastClass.getMethod(methodName,parameterTypes);
		Object result = serviceFastMethod.invoke(serviceBean, parameters);
		return result;
	}

}
